package Stock;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class TradingStock {

	private Stock m_CalculatedStock;
	private byte BASELINE = 2;
	private Float m_stopValue ;
	private Float m_restartValue;
	private Transaction m_lastGrowingTransaction;
	private Transaction m_totalGrowthTransaction;
	private Transaction m_newGrowthBaseTranscation;
	private List<Transaction> m_calculatedTransactions;
	private List<Long> m_StopTradingDates;
	private List<Long> m_StartTradingDates;
	
	private boolean m_live=true;
	
	public Stock getCalculatedStock() {
		return m_CalculatedStock;
	}
	public List<Long> getStopTradingDates() {
		return m_StopTradingDates;
	}
	public List<Long> getStartTradingDates() {
		return m_StartTradingDates;
	}
	

	public TradingStock(Stock stock) {
		this(stock, Byte.parseByte("2"));
	}

	public TradingStock(Stock stock, byte baseline) {
		
		if(baseline>0 && baseline <=8){
			BASELINE = baseline;
		}
		
		System.out.println("baseline:" + BASELINE );
		m_StopTradingDates = new ArrayList<>();
		m_StartTradingDates = new ArrayList<>();
		calculateStock(stock);
		
	}

	private void calculateStock(Stock stock) {
		List<Float> atrList = stock.getATR();
		List<Transaction> transactions = stock.getStockTransactions();
		
		m_calculatedTransactions = new ArrayList<>();
	    m_lastGrowingTransaction = new Transaction(0, 0, 0, 0, 0,	new Date());
	    m_totalGrowthTransaction = m_lastGrowingTransaction;
	    m_newGrowthBaseTranscation=m_lastGrowingTransaction;
	    
		m_stopValue = getStopValue(transactions.get(0).getClose(), atrList.get(0));
		m_restartValue = m_stopValue;
 
		for(int i = 0; i<transactions.size();i++ )
		{
			Float stopValueCheck = getStopValue(transactions.get(i).getClose(), atrList.get(i));
			if(isMakingProfit(stopValueCheck))
			{
				liveTrading(stopValueCheck,transactions.get(i));
			}
			else
			{
				if(isMakingToMuchLoss(transactions.get(i)))
				{
					paperTrading(transactions.get(i),atrList.get(i));
				}
				else
				{
					if(m_live)
					{
						submitLiveTrading(transactions.get(i));
					}
					else
					{
						liveTrading(stopValueCheck,transactions.get(i));
					}
				}
				 
			}
		}
 
		try {
			m_CalculatedStock = new Stock("Trading Stock",
					m_calculatedTransactions, stock.getStatus(),
					stock.getStartValue(), stock.getStartDate());
		} catch (Exception e) {

			e.printStackTrace();
		}
	}
 
	private boolean isMakingToMuchLoss(Transaction transaction) {
		return m_stopValue >  transaction.getClose();
		 
	}

	private boolean isMakingProfit(Float stopValueCheck) {
		return m_stopValue< stopValueCheck;
		 
	}

	private void paperTrading(Transaction transaction,Float ATR) {
	//	System.out.println("PaperTrading!");
		//Go to papertrading


		if(m_live)
		{
			m_StopTradingDates.add(m_calculatedTransactions.get(m_calculatedTransactions.size()-1).getStockDate().getTime());
			m_live=false;
		}

		m_calculatedTransactions.add(new Transaction(
										(m_lastGrowingTransaction.getOpen()-m_newGrowthBaseTranscation.getOpen())+m_totalGrowthTransaction.getOpen(),
										(m_lastGrowingTransaction.getHigh()-m_newGrowthBaseTranscation.getHigh())+m_totalGrowthTransaction.getHigh(),
										(m_lastGrowingTransaction.getLow()-m_newGrowthBaseTranscation.getLow())+m_totalGrowthTransaction.getLow(),
										(m_lastGrowingTransaction.getClose()-m_newGrowthBaseTranscation.getClose())+m_totalGrowthTransaction.getClose(),
										(m_lastGrowingTransaction.getAdjustmentClose()-m_newGrowthBaseTranscation.getAdjustmentClose())+m_totalGrowthTransaction.getAdjustmentClose(),
										transaction.getStockDate())
									);
		Float lowestRestart = getRestartValue(transaction.getClose(), ATR);
		if(m_restartValue > lowestRestart)
			m_restartValue = lowestRestart;
		
		if(transaction.getClose() > m_restartValue)
		{
			//begin trading
			m_stopValue = m_restartValue;
			float open=(m_lastGrowingTransaction.getOpen()+m_totalGrowthTransaction.getOpen())-m_newGrowthBaseTranscation.getOpen();
			float high=(m_lastGrowingTransaction.getHigh()+m_totalGrowthTransaction.getHigh())-m_newGrowthBaseTranscation.getHigh();
			float low=(m_lastGrowingTransaction.getLow()+m_totalGrowthTransaction.getLow())-m_newGrowthBaseTranscation.getLow();
			float close=(m_lastGrowingTransaction.getClose()+m_totalGrowthTransaction.getClose())-m_newGrowthBaseTranscation.getClose();
			float adjclose=(m_lastGrowingTransaction.getAdjustmentClose()+m_totalGrowthTransaction.getAdjustmentClose())-m_newGrowthBaseTranscation.getAdjustmentClose();
			
			m_newGrowthBaseTranscation=transaction;
			
			m_totalGrowthTransaction.SetValues(open, high, low, close, adjclose);
		}
		
	}

	private void liveTrading(Float stopValueCheck, Transaction transaction) {
		m_stopValue = stopValueCheck;
		m_restartValue = m_stopValue;
		
		if(!m_live)
		{
			m_live=true;
			m_StartTradingDates.add(m_calculatedTransactions.get(m_calculatedTransactions.size()-1).getStockDate().getTime());
		}
		
		submitLiveTrading(transaction);
	}
	
	private void submitLiveTrading(Transaction transaction) {
		//System.out.println("Losing money");
		//daling merkbaar, maar geen groot verlies
		m_lastGrowingTransaction=transaction;
		
		Transaction caclulatedTransaction=new Transaction((transaction.getOpen()-m_newGrowthBaseTranscation.getOpen())+m_totalGrowthTransaction.getOpen(),
				(transaction.getHigh()-m_newGrowthBaseTranscation.getHigh())+m_totalGrowthTransaction.getHigh(),
				(transaction.getLow()-m_newGrowthBaseTranscation.getLow())+m_totalGrowthTransaction.getLow(),
				(transaction.getClose()-m_newGrowthBaseTranscation.getClose())+m_totalGrowthTransaction.getClose(),
				(transaction.getAdjustmentClose()-m_newGrowthBaseTranscation.getAdjustmentClose())+m_totalGrowthTransaction.getAdjustmentClose(),transaction.getStockDate());
		
		m_calculatedTransactions.add(caclulatedTransaction);
		
	}

	private Float getStopValue(Float OHLCvalue, Float atr) {
		return OHLCvalue - (BASELINE * atr);
	}
	
	private Float getRestartValue(Float OHLCvalue, Float atr) {
		return OHLCvalue + (BASELINE * atr);
	}
}